home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / lang / p_image1.sit / LSP Source / Graphics.p < prev    next >
Encoding:
Text File  |  1989-07-29  |  28.3 KB  |  1,198 lines

  1. unit Graphics;
  2.  
  3. {Graphics routines used by Image program}
  4.  
  5. interface
  6.  
  7.     uses
  8.         QuickDraw, ToolIntf, PickerIntf, OSIntf, PrintTraps, globals, Utilities;
  9.  
  10.     procedure DoPlot (event: EventRecord; start, finish: point);
  11.     procedure DrawPlot;
  12.     procedure ShowResults;
  13.     procedure SetupPlot (var data: LineType; start: point);
  14.     procedure MakePlotWindow (PlotLeft, PlotTop, PlotWidth, PlotHeight: integer);
  15.     procedure DrawObject (obj: ObjectType; p1, p2: point);
  16.     procedure DrawLUT;
  17.     procedure DrawTools;
  18.     procedure DrawHistogram;
  19.     procedure DrawGrayMap;
  20.     procedure ResetGrayMap;
  21.     procedure DoMouseDownInGrayMap;
  22.  
  23. implementation
  24.  
  25.  
  26.     procedure DrawNum (x, y: integer; value: LongInt);
  27.         var
  28.             str: str255;
  29.     begin
  30.         MoveTo(x, y);
  31.         if value < 10 then
  32.             DrawString('0');
  33.         if value < 100 then
  34.             DrawString('0');
  35.         NumToString(value, str);
  36.         DrawString(str);
  37.     end;
  38.  
  39.  
  40.     procedure LabelProfilePlot;
  41.         var
  42.             str: str255;
  43.             min, max: extended;
  44.     begin
  45.         if InvertPlots then begin
  46.                 min := PlotMax;
  47.                 max := PlotMin
  48.             end
  49.         else begin
  50.                 min := PlotMin;
  51.                 max := PlotMax
  52.             end;
  53.         if info^.Calibrated then begin
  54.                 MoveTo(2, PlotHeight - PlotBottomMargin);
  55.                 DrawReal(Min, 1, 2);
  56.                 MoveTo(2, PlotTopMargin + 8);
  57.                 DrawReal(Max, 1, 2);
  58.             end
  59.         else begin
  60.                 DrawNum(2, PlotHeight - PlotBottomMargin, trunc(Min));
  61.                 DrawNum(2, PlotTopMargin + 8, trunc(Max));
  62.             end;
  63.         MoveTo(PlotLeftMargin + 15, PlotHeight - PlotBottomMargin + 12);
  64.         DrawString('N=');
  65.         NumToString(PlotCount, str);
  66.         DrawString(str);
  67.         DrawString('     Mean=');
  68.         RealToString(PlotMean, 3, 2, str);
  69.         DrawString(str);
  70.         if PlotAvg > 1 then begin
  71.                 DrawString('    Width=');
  72.                 NumToString(PlotAvg, str);
  73.                 DrawString(str);
  74.             end;
  75.         DrawString('    ');
  76.         if info^.Calibrated then begin
  77.                 DrawString('Calibrated(');
  78.                 DrawString(info^.UnitOfMeasure);
  79.                 DrawString(')');
  80.             end
  81.         else
  82.             DrawString('Uncalibrated');
  83.     end;
  84.  
  85.  
  86.     procedure LabelCalibrationPlot;
  87.         var
  88.             pbottom, hloc, vloc, i: integer;
  89.             letter: packed array[1..6] of char;
  90.     begin
  91.         pbottom := PlotHeight - PLotBottomMargin;
  92.         MoveTo(2, PlotTopMargin + 4);
  93.         DrawReal(MaxValue, 4, 2);
  94.         MoveTo(2, pbottom);
  95.         DrawReal(MinValue, 4, 2);
  96.         MoveTo(PlotLeftMargin - 3, pbottom + 10);
  97.         DrawString('0');
  98.         MoveTo(PlotWidth - PlotRightMargin - 14, pbottom + 10);
  99.         DrawString('255');
  100.         MoveTo(PlotLeftMargin + 15, PlotTopMargin + 15);
  101.         TextSize(12);
  102.         case info^.fit of
  103.             StrightLine: 
  104.                 DrawString('y=a+bx');
  105.             Poly2: 
  106.                 DrawString('y=a+bx+cx^2');
  107.             Poly3: 
  108.                 DrawString('y=a+bx+cx^2+dx^3');
  109.             Poly4: 
  110.                 DrawString('y=a+bx+cx^2+dx^3+ex^4');
  111.             Poly5: 
  112.                 DrawString('y=a+bx+cx^2+dx^3+ex^4+fx^5');
  113.             ExpoFit: 
  114.                 DrawString('y=aexp(bx)');
  115.             PowerFit: 
  116.                 DrawString('y=ax^b');
  117.             LogFit: 
  118.                 DrawString('y=aln(bx)');
  119.         end;
  120.         hloc := PlotWidth - PlotRightMargin + 5;
  121.         vloc := PlotTopMargin + 25;
  122.         letter := 'abcdef';
  123.         MoveTo(hloc, vloc);
  124.         with info^ do
  125.             for i := 1 to nCoefficients do begin
  126.                     MoveTo(hloc, vloc);
  127.                     TextSize(12);
  128.                     DrawString(letter[i]);
  129.                     DrawString('=');
  130.                     TextSize(9);
  131.                     DrawReal(Coefficient[i], 1, 8);
  132.                     vloc := vloc + 15;
  133.                 end;
  134.         vloc := vloc + 25;
  135.         MoveTo(hloc, vloc);
  136.         DrawString('S.D.=');
  137.         DrawReal(FitSD, 1, 4);
  138.         vloc := vloc + 15;
  139.         MoveTo(hloc, vloc);
  140.         DrawString('R^2=');
  141.         DrawReal(FitGoodness, 1, 4);
  142.     end;
  143.  
  144.  
  145.     procedure DrawPlot;
  146.         var
  147.             tPort: GrafPtr;
  148.             fRect: rect;
  149.     begin
  150.         if not Printing then begin
  151.                 GetPort(tPort);
  152.                 SetPort(PlotWindow);
  153.                 EraseRect(PlotWindow^.portRect);
  154.             end;
  155.         SetRect(fRect, PlotLeftMargin, PlotTopMargin, PlotWidth - PlotRightMargin, PlotHeight - PlotBottomMargin);
  156.         PenNormal;
  157.         FrameRect(fRect);
  158.         DrawPicture(PlotPICT, fRect);
  159.         TextFont(ApplFont);
  160.         TextSize(9);
  161.         if WindowPeek(PlotWindow)^.WindowKind = ProfilePlotKind then begin
  162.                 if DrawPlotLabels then
  163.                     LabelProfilePlot
  164.             end
  165.         else
  166.             LabelCalibrationPlot;
  167.         if not printing then begin
  168.                 if not Copying then
  169.                     DrawMyGrowIcon(PlotWindow);
  170.                 SetPort(tPort);
  171.             end;
  172.     end;
  173.  
  174.  
  175.     procedure MakePlotWindow; {(PlotLeft, PlotTop, PlotWidth, PlotHeight: integer)}
  176.         var
  177.             PLotRect, pwrect, dwrect, srect: rect;
  178.             overlapping: boolean;
  179.     begin
  180.         if PlotWindow = nil then begin
  181.                 SetRect(PlotRect, PlotLeft, PlotTop, PlotLeft + PlotWidth, PlotTop + PlotHeight);
  182.                 PlotWindow := NewWindow(nil, PlotRect, 'Plot', true, DocumentProc, nil, true, 0);
  183.                 SetMenuItem(GetMHandle(WindowsMenu), 8, true);
  184.             end
  185.         else begin
  186.                 GetWindowRect(PlotWindow, pwrect);
  187.                 GetWindowRect(info^.wptr, dwrect);
  188.                 overlapping := SectRect(pwrect, dwrect, srect);
  189.                 if overlapping then
  190.                     MoveWindow(PlotWindow, PlotLeft, PlotTop, false);
  191.                 SizeWindow(PlotWindow, PlotWidth, PlotHeight, false);
  192.             end;
  193.     end;
  194.  
  195.  
  196.     procedure SetupPlot; {(var data: LineType; start: point)}
  197.         var
  198.             fRect: rect;
  199.             tPort: GrafPtr;
  200.             i, width, y, fmax: integer;
  201.             ClipRegion, SaveClipRegion: RgnHandle;
  202.             pt: point;
  203.             temp, sum, vscale: extended;
  204.             AutoScale: boolean;
  205.             RealData: array[0..MaxPixelsPerLine] of extended;
  206.             index: UnsignedByte;
  207.     begin
  208.         if info^.calibrated then
  209.             PlotLeftMargin := 35
  210.         else
  211.             PlotLeftMargin := 25;
  212.         PlotTopMargin := 10;
  213.         PlotBottomMargin := 20;
  214.         PlotRightMargin := 10;
  215.         for i := 0 to PlotCount - 1 do
  216.             RealData[i] := value[data[i]];
  217.         if InvertPlots then
  218.             for i := 0 to PlotCount - 1 do
  219.                 RealData[i] := MaxValue - RealData[i];
  220.         if FixedSizePlot then begin
  221.                 width := ProfilePlotWidth;
  222.                 PlotWidth := width;
  223.                 PlotHeight := ProfilePlotHeight
  224.             end
  225.         else begin
  226.                 Width := PlotCount * trunc(Info^.magnification + 0.5);
  227.                 if Width < 50 then
  228.                     Width := 100;
  229.                 PlotHeight := Width div 2;
  230.                 if PlotWidth > 300 then
  231.                     PlotHeight := width div 3;
  232.                 if PlotWidth > 400 then
  233.                     PlotHeight := width div 4;
  234.             end;
  235.         PlotWidth := Width + PlotLeftMargin + PlotRightMargin;
  236.         PlotHeight := PlotHeight + PlotTopMargin + PlotBottomMargin;
  237.         pt.h := start.h;
  238.         pt.v := start.v + 40;
  239.         LocalToGlobal(pt);
  240.         PlotLeft := pt.h - PlotLeftMargin;
  241.         PlotTop := pt.v;
  242.         if PlotTop > (ScreenHeight - PlotHeight) then
  243.             PlotTop := PlotTop - PlotHeight - 60;
  244.         if PlotTop < 60 then
  245.             PlotTop := 60;
  246.         MakePlotWindow(PlotLeft, PlotTop, PlotWidth, PlotHeight);
  247.         WindowPeek(PlotWindow)^.WindowKind := ProfilePlotKind;
  248.         PlotMin := MinValue;
  249.         PlotMax := MaxValue;
  250.         sum := 0.0;
  251.         for i := 0 to PlotCount - 1 do begin
  252.                 temp := RealData[i];
  253.                 sum := sum + temp;
  254.                 if AutoscalePlots then begin
  255.                         if temp < PlotMin then
  256.                             PlotMin := temp;
  257.                         if temp > PlotMax then
  258.                             PlotMax := temp;
  259.                     end;
  260.             end;
  261.         if PlotCount > 0 then
  262.             PlotMean := sum / PlotCount
  263.         else
  264.             PlotMean := 0.0;
  265.         if not AutoscalePlots then begin
  266.                 PlotMin := ProfilePlotMin;
  267.                 PlotMax := ProfilePlotMax;
  268.             end;
  269.         fmax := PlotCount - 1;
  270.         if (PlotMax - PlotMin) <> 0 then
  271.             vscale := fmax / (PlotMax - PlotMin)
  272.         else
  273.             vscale := 1.0;
  274.         SetRect(fRect, 0, 0, fmax, fmax);
  275.         GetPort(tPort);
  276.         SetPort(PlotWindow);
  277.         SaveClipRegion := PlotWindow^.ClipRgn;
  278.         ClipRegion := NewRgn;
  279.         OpenRgn;
  280.         FrameRect(fRect);
  281.         CloseRgn(ClipRegion);
  282.         PlotWindow^.ClipRgn := ClipRegion;
  283.         PlotPICT := OpenPicture(fRect);
  284.         PenNormal;
  285.         if LinePlot then begin
  286.                 MoveTo(0, round(vscale * (PlotMax - RealData[0])));
  287.                 for i := 1 to PlotCount - 1 do
  288.                     LineTo(i, round(vscale * (PlotMax - RealData[i])))
  289.             end
  290.         else
  291.             for i := 1 to PlotCount - 1 do begin
  292.                     y := round(vscale * (PlotMax - RealData[i]));
  293.                     MoveTo(i, y);
  294.                     LineTo(i, y)
  295.                 end;
  296.         ClosePicture;
  297.         PlotWindow^.ClipRgn := SaveClipRegion;
  298.         DisposeRgn(ClipRegion);
  299.         InvalRect(PlotWindow^.PortRect);
  300.         SetPort(tPort);
  301.         SelectWindow(PlotWindow);
  302.     end;
  303.  
  304.  
  305.     procedure DoPlot;{ (event: EventRecord; start, finish: point)}
  306.         var
  307.             i, range, width, value: integer;
  308.             p1, p2, pt: point;
  309.     begin
  310.         with Info^.wrect do begin
  311.                 if finish.h >= right then
  312.                     finish.h := right - 1;
  313.                 if finish.v >= bottom then
  314.                     finish.v := bottom - 1;
  315.             end;
  316.         if finish.h < start.h then begin {Swap ends}
  317.                 pt := start;
  318.                 start := finish;
  319.                 finish := pt;
  320.             end;
  321.         p1 := start;
  322.         p2 := finish;
  323.         ScreenToOffscreen(p1);
  324.         ScreenToOffscreen(p2);
  325.         GetDiagLine(p1, p2, PlotCount, PlotData);
  326.         PlotAvg := LineWidth;
  327.         SetupPlot(PlotData, start);
  328.     end;
  329.  
  330.  
  331.     procedure FilterHistogram (var h: HistogramType);
  332.         var
  333.             i: integer;
  334.     begin
  335.         for i := 1 to 254 do
  336.             h[i] := (h[i - 1] + h[i] + h[i + 1]) div 3;
  337.     end;
  338.  
  339.  
  340.  
  341.     procedure ShowResults;
  342.         var
  343.             vloc, hloc, i: integer;
  344.             tPort: GrafPtr;
  345.             trect: rect;
  346.             clength, cx, cy, IntDen, BackgroundLevel: extended;
  347.             MaxCount: LongInt;
  348.             h: HistogramType;
  349.  
  350.         procedure NewLine;
  351.         begin
  352.             vloc := vloc + 12;
  353.             MoveTo(hloc, vloc);
  354.         end;
  355.  
  356.     begin
  357.         GetPort(tPort);
  358.         vloc := 35;
  359.         hloc := 4;
  360.         SetPort(ResultsWindow);
  361.         TextFont(ApplFont);
  362.         TextSize(9);
  363.         Setrect(trect, 0, vloc, rwidth, rheight);
  364.         EraseRect(trect);
  365.         with results do begin
  366.                 NewLine;
  367.                 case CurrentTool of
  368.                     ruler: 
  369.                         with info^ do begin
  370.                                 DrawBString('Count: ');
  371.                                 DrawLong(nLengths);
  372.                                 NewLine;
  373.                                 DrawBString('Length: ');
  374.                                 DrawReal(lengths[nLengths], 1, 2);
  375.                                 DrawString(' ');
  376.                                 if scale <> 0.0 then
  377.                                     DrawString(Units)
  378.                                 else
  379.                                     DrawString('Pixels');
  380.                                 NewLine;
  381.                                 DrawBString('Total: ');
  382.                                 DrawReal(TotalLength, 1, 2);
  383.                             end;
  384.                     PointingTool: 
  385.                         begin
  386.                             DrawBString('Count: ');
  387.                             DrawLong(nPoints);
  388.                             NewLine;
  389.                             DrawBString('X: ');
  390.                             DrawReal(x, 1, 2);
  391.                             NewLine;
  392.                             DrawBString('Y: ');
  393.                             DrawReal(y, 1, 2);
  394.                         end;
  395.                     AngleTool: 
  396.                         begin
  397.                             DrawBString('Angle: ');
  398.                             DrawReal(angle, 1, 2);
  399.                             DrawString(' degrees');
  400.                             NewLine;
  401.                         end;
  402.                     otherwise
  403.                         with info^ do begin
  404.                                 DrawBString('Count: ');
  405.                                 DrawLong(nAreas);
  406.                                 NewLine;
  407.                                 DrawBString('N: ');
  408.                                 DrawLong(n);
  409.                                 if scale <> 0.0 then begin
  410.                                         NewLine;
  411.                                         DrawBString('Area: ');
  412.                                         DrawReal(n / sqr(scale), 1, 2);
  413.                                         DrawString(' square ');
  414.                                         DrawString(units);
  415.                                     end;
  416.                                 NewLine;
  417.                                 DrawBString('Mean: ');
  418.                                 DrawReal(mean[nAreas], 1, 2);
  419.                                 if calibrated then begin
  420.                                         DrawString(' ');
  421.                                         DrawBString(UnitOfMeasure);
  422.                                         DrawString('   (');
  423.                                         DrawLong(results.imean);
  424.                                         DrawString(')');
  425.                                     end;
  426.                                 if BinaryPic then begin
  427.                                         NewLine;
  428.                                         DrawBString('Black: ');
  429.                                         DrawLong(histogram[255]);
  430.                                         NewLine;
  431.                                         DrawBString('White: ');
  432.                                         DrawLong(histogram[0]);
  433.                                     end
  434.                                 else begin
  435.                                         if (imin = 0) or (imin = 1) or (imax = 255) or (imax = 254) then
  436.                                             DrawBString(' (Possible Saturation)');
  437.                                         NewLine;
  438.                                         DrawBString('Std Dev: ');
  439.                                         DrawReal(SD[nAreas], 1, 4);
  440.                                         NewLine;
  441.                                         DrawBString('Min: ');
  442.                                         DrawReal(min, 1, 2);
  443.                                         NewLine;
  444.                                         DrawBString('Max: ');
  445.                                         DrawReal(max, 1, 2);
  446.                                     end;
  447.                                 if xyLocM in Measurements then begin
  448.                                         NewLine;
  449.                                         DrawBString('X,Y: ');
  450.                                         DrawReal(xcenter[nAreas], 6, 2);
  451.                                         DrawString(',');
  452.                                         DrawReal(ycenter[nAreas], 6, 2);
  453.                                     end;
  454.                                 if ModeM in Measurements then begin
  455.                                         NewLine;
  456.                                         DrawBString('Mode: ');
  457.                                         DrawReal(mode[nAreas], 1, 2);
  458.                                     end;
  459.                                 if IntDenM in measurements then begin
  460.                                         NewLine;
  461.                                         h := histogram;
  462.                                         FilterHistogram(h);
  463.                                         FilterHistogram(h);
  464.                                         FilterHistogram(h);
  465.                                         BackgroundLevel := 0.0;
  466.                                         MaxCount := 0;
  467.                                         for i := 0 to 255 do
  468.                                             if h[i] > MaxCount then begin
  469.                                                     MaxCount := h[i];
  470.                                                     BackgroundLevel := value[i]
  471.                                                 end;
  472.                                         IntDen := n * (mean[nAreas] - BackgroundLevel);
  473.                                         DrawBString('Integrated Density: ');
  474.                                         DrawReal(IntDen, 1, 2);
  475.                                         NewLine;
  476.                                         DrawBString('Background Level: ');
  477.                                         DrawReal(BackGroundLevel, 1, 2);
  478.                                     end
  479.                                 else
  480.                                     IntDen := 0.0;
  481.                                 IntegratedDensity[nAreas] := IntDen;
  482.                                 if PerimeterM in measurements then begin
  483.                                         NewLine;
  484.                                         DrawBString('Perimeter Length: ');
  485.                                         DrawReal(plength[nAreas], 1, 2);
  486.                                     end;
  487.                             end;
  488.                 end; {case}
  489.             end; {with}
  490.         SetPort(tPort);
  491.         nAreas2 := nAreas;
  492.     end;
  493.  
  494.  
  495.     procedure PaintCircle (hloc, vloc: integer);
  496.         var
  497.             r: rect;
  498.     begin
  499.         SetRect(r, hloc, vloc, hloc + LineWidth, vloc + LineWidth);
  500.         PaintOval(r);
  501.     end;
  502.  
  503.  
  504.     procedure DrawBrush (start, finish: point);
  505.   {Thanks to Robert Rimmer for suggesting the use of a line generator to implement the brush.}
  506.         var
  507.             deltax, deltay, xinc, yinc, accumulator, i: integer;
  508.             xloc, yloc, offset, j: integer;
  509.     begin
  510.         xloc := start.h;
  511.         yloc := start.v;
  512.         deltax := finish.h - xloc;
  513.         deltay := finish.v - yloc;
  514.         if (deltax = 0) and (deltay = 0) then begin
  515.                 PaintCircle(xloc, yloc);
  516.                 exit(DrawBrush)
  517.             end;
  518.         if deltax < 0 then begin
  519.                 xinc := -1;
  520.                 deltax := -deltax
  521.             end
  522.         else
  523.             xinc := 1;
  524.         if deltay < 0 then begin
  525.                 yinc := -1;
  526.                 deltay := -deltay
  527.             end
  528.         else
  529.             yinc := 1;
  530.         if DeltaX > DeltaY then begin {More horizontal}
  531.                 accumulator := deltax div 2;
  532.                 i := deltax;
  533.                 repeat
  534.                     accumulator := accumulator + deltay;
  535.                     if accumulator >= deltax then begin
  536.                             accumulator := accumulator - deltax;
  537.                             yloc := yloc + yinc
  538.                         end;
  539.                     xloc := xloc + xinc;
  540.                     PaintCircle(xloc, yloc);
  541.                     i := i - 1;
  542.                 until i = 0
  543.             end
  544.         else begin          {More vertical}
  545.                 accumulator := deltay div 2;
  546.                 i := deltay;
  547.                 repeat
  548.                     accumulator := accumulator + deltax;
  549.                     if accumulator >= deltay then begin
  550.                             accumulator := accumulator - deltay;
  551.                             xloc := xloc + xinc
  552.                         end;
  553.                     yloc := yloc + yinc;
  554.                     PaintCircle(xloc, yloc);
  555.                     i := i - 1;
  556.                 until i = 0
  557.             end;
  558.     end;
  559.  
  560.  
  561.     procedure DrawObject;{ (obj: ObjectType; p1, p2: point)}
  562.         var
  563.             MaskRect, r, dstRect, osMaskRect: rect;
  564.             tPort: GrafPtr;
  565.             tmp: integer;
  566.     begin
  567.         GetPort(tPort);
  568.         Pt2Rect(p1, p2, MaskRect);
  569.         with Info^ do begin
  570.                 changes := true;
  571.                 tmp := trunc(magnification + 0.5) * LineWidth;
  572.                 with MaskRect do begin
  573.                         if tmp < 32 then
  574.                             tmp := 32;
  575.                         right := right + tmp;
  576.                         bottom := bottom + tmp;
  577.                         if magnification > 1.0 then begin
  578.                                 left := left - tmp;
  579.                                 top := top - tmp;
  580.                             end;
  581.                     end;
  582.                 ScreenToOffscreen(p1);
  583.                 ScreenToOffscreen(p2);
  584.                 SetPort(GrafPtr(osPort));
  585.                 PenNormal;
  586.                 PenSize(LineWidth, LineWidth);
  587.                 case obj of
  588.                     lineObj: 
  589.                         begin
  590.                             MoveTo(p1.h, p1.v);
  591.                             LineTo(p2.h, p2.v);
  592.                         end;
  593.                     Rectangle: 
  594.                         begin
  595.                             Pt2Rect(p1, p2, r);
  596.                             FrameRect(r);
  597.                         end;
  598.                     RoundedRect: 
  599.                         begin
  600.                             Pt2Rect(p1, p2, r);
  601.                             FrameRoundRect(r, OvalSize, OvalSize);
  602.                         end;
  603.                     oval: 
  604.                         begin
  605.                             Pt2Rect(p1, p2, r);
  606.                             FrameOval(r);
  607.                         end;
  608.                     BrushObj: 
  609.                         DrawBrush(p1, p2);
  610.                 end;
  611.                 SetPort(tPort);
  612.                 RectRgn(MaskRgn, MaskRect);
  613.                 hlock(handle(osPort^.portPixMap));
  614.                 hlock(handle(CGrafPort(ThePort^).PortPixMap));
  615.                 CopyBits(BitMapHandle(osPort^.portPixMap)^^, BitMapHandle(CGrafPort(ThePort^).PortPixMap)^^, SrcRect, wrect, SrcCopy, MaskRgn);
  616.                 hunlock(handle(osPort^.portPixMap));
  617.                 hunlock(handle(CGrafPort(ThePort^).PortPixMap));
  618.             end; {with}
  619.     end;
  620.  
  621.  
  622.     procedure DrawLUT;
  623.         var
  624.             tPort: GrafPtr;
  625.             h, v, i: integer;
  626.     begin
  627.         GetPort(tPort);
  628.         SetPort(LUTWindow);
  629.         with ThePort^ do begin
  630.                 for v := 0 to 255 do begin
  631.                         fgColor := v;
  632.                         MoveTo(0, v);
  633.                         LineTo(cwidth, v)
  634.                     end;
  635.                 for i := 1 to nExtraColors + 2 do begin
  636.                         fgColor := ExtraColorsEntry[i];
  637.                         PaintRect(ExtraColorsRect[i]);
  638.                     end;
  639.                 TextFont(ApplFont);
  640.                 TextSize(9);
  641.                 with ExtraColorsRect[1] do
  642.                     MoveTo(left + 3, bottom - 1);
  643.                 fgcolor := BlackC;
  644.                 DrawString('white');
  645.                 with ExtraColorsRect[2] do
  646.                     MoveTo(left + 4, bottom - 1);
  647.                 InvertRect(ExtraColorsRect[2]);
  648.                 DrawString('black');
  649.                 InvertRect(ExtraColorsRect[2]);
  650.             end;
  651.         SetPort(tPort);
  652.     end;
  653.  
  654.  
  655.     procedure GetRGBColors (var ForegroundRGB, BackgroundRGB: RGBColor);
  656.     begin
  657.         ForegroundRGB := info^.cTable[ForegroundColor].rgb;
  658.         if ForegroundColor = 0 then
  659.             ForegroundRGB := WhiteRGB;
  660.         if ForegroundColor = 255 then
  661.             ForegroundRGB := BlackRGB;
  662.         if nExtraColors > 0 then begin
  663.                 if (ForegroundColor >= FirstExtraColorsEntry) and (ForegroundColor < (FirstExtraColorsEntry + nExtraColors)) then
  664.                     ForegroundRGB := ExtraColors[ForegroundColor - FirstExtraColorsEntry + 1];
  665.             end;
  666.         BackgroundRGB := info^.cTable[BackgroundColor].rgb;
  667.         if BackgroundColor = 0 then
  668.             BackgroundRGB := WhiteRGB;
  669.         if BackgroundColor = 255 then
  670.             BackgroundRGB := BlackRGB;
  671.         if nExtraColors > 0 then begin
  672.                 if (BackgroundColor >= FirstExtraColorsEntry) and (BackgroundColor < (FirstExtraColorsEntry + nExtraColors)) then
  673.                     BackgroundRGB := ExtraColors[BackgroundColor - FirstExtraColorsEntry + 1];
  674.             end;
  675.     end;
  676.  
  677.     procedure DrawTools;
  678.         var
  679.             tPort: GrafPtr;
  680.             v, n, i: integer;
  681.             str: str255;
  682.             tool: ToolType;
  683.             ForegroundRGB, BackgroundRGB: RGBColor;
  684.     begin
  685.         GetPort(tPort);
  686.         SetPort(ToolWindow);
  687.         TextFont(ToolFont);
  688.         TextSize(12);
  689.         EraseRect(CGrafPort(ToolWindow^).PortPixMap^^.bounds);
  690.         for tool := FirstTool to LastTool do
  691.             with ToolRect[tool] do begin
  692.                     MoveTo(left + ho, top + vo);
  693.                     DrawChar(ToolChar[tool]);
  694.                 end;
  695.         InvertRect(ToolRect[CurrentTool]);
  696. {ToolWindow^.fgColor := ForegroundColor;}
  697.         GetRGBColors(ForegroundRGB, BackgroundRGB);
  698.         RGBForeColor(ForegroundRGB);
  699.         with ToolRect[brush] do
  700.             MoveTo(left + ho, top + vo);
  701.         DrawChar(chr(80));
  702. {ToolWindow^.fgColor := BackgroundColor;}
  703.         RGBForeColor(BackgroundRGB);
  704.         with ToolRect[Eraser] do
  705.             MoveTo(left + ho, top + vo);
  706.         DrawChar(chr(102));
  707. {ToolWindow^.fgColor := BlackC;}
  708.         RGBForeColor(BlackRGB);
  709.         for i := 1 to nLineTypes do
  710.             PaintRect(lines[i]);
  711.         MoveTo(0, Lines[LineIndex].top - 9);
  712.         DrawChar(chr(CheckMarkChar));
  713.         SetPort(tPort);
  714.     end;
  715.  
  716.  
  717.     procedure DrawHistogram;
  718.         var
  719.             tPort: GrafPtr;
  720.             h, scale, NonZero, hstart, hend: integer;
  721.             v, MaxCount, count: LongInt;
  722.             str: str255;
  723.     begin
  724.         if not printing then begin
  725.                 GetPort(tPort);
  726.                 SetPort(HistoWindow);
  727.                 EraseRect(HistoWindow^.portRect);
  728.             end;
  729.         with results do begin
  730.                 MaxCount := histogram[imode];
  731.                 if MaxCount > (hheight - 2) then begin
  732.                         scale := trunc(MaxCount / (hheight - 2));
  733.                         scale := scale + 1
  734.                     end
  735.                 else
  736.                     scale := 1;
  737.                 NonZero := 0;
  738.                 if Thresholding then begin
  739.                         hstart := ThresholdStart;
  740.                         hend := ThresholdEnd
  741.                     end
  742.                 else begin
  743.                         hstart := 0;
  744.                         hend := 255
  745.                     end;
  746.                 for h := hstart to hend do begin
  747.                         MoveTo(h, hheight);
  748.                         count := histogram[h];
  749.                         v := hheight - (count div scale);
  750.                         if v < 0 then
  751.                             v := 0;
  752.                         LineTo(h, v);
  753.                         if count > 0 then
  754.                             NonZero := NonZero + 1;
  755.                     end;
  756.             end;
  757.         if not Printing then
  758.             SetPort(tPort);
  759.         LoadLUT(info^.cTable);
  760.     end;
  761.  
  762.  
  763.     procedure UpdateGrayMap;
  764.         const
  765.             gmRectArea = 4096.0; {64x64}
  766.             max = 4177920;
  767.         var
  768.             tPort: GrafPtr;
  769.             r: rect;
  770.             x, y, i, h1, h2, h3, v1, v2, v3, dx, dy: integer;
  771.             xcenter, ycenter, brightness, islope, thumb: integer;
  772.             table: LookupTable;
  773.             hrect: rect;
  774.             slope: extended;
  775.             area, value, sum: LongInt;
  776.     begin
  777.         GetPort(tPort);
  778.         SetPort(GrayMapWindow);
  779.         PenNormal;
  780.         EraseRect(GrayMapRect2);
  781.         FrameRect(GrayMapRect);
  782.         with info^ do
  783.             if LutMode = CustomGrayscale then begin
  784.                     GetLookupTable(table);
  785.                     for i := 0 to 63 do begin
  786.                             x := gmRectLeft + 63 - i;
  787.                             y := gmRectTop + table[i * 4] div 4;
  788.                             MoveTo(x, y);
  789.                             LineTo(x, y);
  790.                         end
  791.                 end
  792.             else begin
  793.                     h1 := gmRectLeft + p1x div 4;
  794.                     v1 := gmRectBottom - 1 - (p1y div 4);
  795.                     h2 := gmRectLeft + p2x div 4;
  796.                     v2 := gmRectBottom - 1 - (p2y div 4);
  797.                     MoveTo(gmRectLeft, gmRectBottom - 1);
  798.                     LineTo(h1, v1);
  799.                     LineTo(h2, v2);
  800.                     LineTo(gmRectRight - 1, gmRectTop);
  801.                     SetRect(hrect, h1 - 1, v1 - 1, h1 + 2, v1 + 2);
  802.                     PaintRect(hrect); {First handle}
  803.                     SetRect(hrect, h2 - 1, v2 - 1, h2 + 2, v2 + 2);
  804.                     PaintRect(hrect); {Last handle}
  805.                     dx := p2x - p1x;
  806.                     dy := p2y - p1y;
  807.                     xcenter := p1x + dx div 2;
  808.                     ycenter := p1y + dy div 2;
  809.                     h3 := gmRectLeft + xcenter div 4;
  810.                     v3 := gmRectBottom - 1 - (ycenter div 4);
  811.                     SetRect(hrect, h3 - 1, v3 - 1, h3 + 2, v3 + 2);
  812.                     PaintRect(hrect); {Center handle}
  813.                     thumb := gmSlideHeight - 2;
  814.                     i := 0;
  815.                     sum := 0;
  816.                     repeat
  817.                         value := ctable[i].rgb.red;
  818.                         value := band(value, 65535);
  819.                         sum := sum + value;
  820.                         i := i + 4;
  821.                     until i > 255;
  822.                     brightness := trunc((sum / max) * (gmSlideWidth - thumb - 2.0));
  823.                     gmSlide1Loc := brightness;
  824.                     with gmSlide1 do
  825.                         SetRect(hrect, left + brightness + 1, top + 1, left + brightness + thumb + 1, top + thumb + 1);
  826.                     EraseRect(gmSlide1i);
  827.                     PaintRect(hrect);  {Thumb for brightness control}
  828.                     if dx <> 0 then
  829.                         slope := dy / dx
  830.                     else
  831.                         slope := 1000.0;
  832.                     if slope > 1.0 then begin
  833.                             if dy <> 0 then
  834.                                 slope := 2.0 - dx / dy
  835.                             else
  836.                                 slope := 2.0;
  837.                         end;
  838.                     islope := trunc(slope * 0.5 * (gmSlideWidth - thumb - 2.0));
  839.                     with gmSlide2 do
  840.                         SetRect(hrect, left + islope + 1, top + 1, left + islope + thumb + 1, top + thumb + 1);
  841.                     EraseRect(gmSlide2i);
  842.                     PaintRect(hrect);  {Thumb for contrast control}
  843.                 end;
  844.         SetPort(tPort);
  845.     end;
  846.  
  847.  
  848.     procedure DrawGrayMap;
  849.         var
  850.             tPort: GrafPtr;
  851.             x, y, i: integer;
  852.             table: LookupTable;
  853.     begin
  854.         GetPort(tPort);
  855.         SetPort(GrayMapWindow);
  856.         PenNormal;
  857.         TextFont(ApplFont);
  858.         TextSize(9);
  859.         with gmSlide1 do
  860.             MoveTo(left - 6, bottom);
  861.         DrawChar('B');
  862.         with gmSlide2 do
  863.             MoveTo(left - 6, bottom);
  864.         DrawChar('C');
  865.         FrameRect(gmSlide1);
  866.         FrameRect(gmSlide2);
  867.         FrameRect(gmIcon1);
  868.         FrameRect(gmIcon2);
  869.         with gmIcon1 do begin
  870.                 MoveTo(left, top + 10);
  871.                 LineTo(left + 5, top + 10);
  872.                 LineTo(left + 12, top + 3);
  873.                 LineTo(left + gmIconWidth - 1, top + 3);
  874.             end;
  875.         with gmIcon2 do begin
  876.                 MoveTo(left, top + 10);
  877.                 LineTo(left + gmIconWidth div 2, top + 10);
  878.                 LineTo(left + gmIconWidth div 2, top + 3);
  879.                 LineTo(left + gmIconWidth - 1, top + 3);
  880.             end;
  881.         UpdateGrayMap;
  882.         GrayMapReady := true;
  883.         SetPort(tPort);
  884.     end;
  885.  
  886.  
  887.     procedure ResetGrayMap;
  888.     begin
  889.         with info^ do begin
  890.                 StopThresholding;
  891.                 p1x := 0;
  892.                 p1y := 0;
  893.                 p2x := 255;
  894.                 p2y := 255;
  895.                 DeltaX := 256;
  896.                 DeltaY := 256;
  897.                 SetGrayScaleLUT;
  898.                 LUTMode := Grayscale;
  899.                 if GrayMapReady then
  900.                     UpdateGrayMap;
  901.                 IdentityFunction := true;
  902.             end;
  903.     end;
  904.  
  905.  
  906.     procedure FindEndPoints (x, y: integer);
  907.         var
  908.             xintercept: integer;
  909.     begin
  910.         with info^ do begin
  911.                 if DeltaX = 0 then begin
  912.                         p1x := x;
  913.                         p1y := 0;
  914.                         p2x := x;
  915.                         p2y := 255;
  916.                         exit(FindEndPoints);
  917.                     end;
  918.                 if DeltaY = 0 then begin
  919.                         p1x := 0;
  920.                         p1y := y;
  921.                         p2x := 255;
  922.                         p2y := y;
  923.                         exit(FindEndPoints);
  924.                     end;
  925.                 p1x := x - y * LongInt(DeltaX) div DeltaY;
  926.                 xIntercept := p1x;
  927.                 p1y := 0;
  928.                 if p1x < 0 then begin
  929.                         p1y := -(LongInt(DeltaY) * p1x) div DeltaX;
  930.                         p1x := 0;
  931.                     end;
  932.                 p2y := 255;
  933.                 p2x := 255 * LongInt(DeltaX) div DeltaY;
  934.                 if xIntercept < 0 then
  935.                     p2x := p2x + xIntercept
  936.                 else
  937.                     p2x := p2x + p1x;
  938.                 if p2x > 255 then begin
  939.                         p2y := 255 - (p2x - 255) * LongInt(DeltaY) div DeltaX;
  940.                         p2x := 255;
  941.                     end;
  942.                 if p2x < 0 then
  943.                     p2x := 0;
  944.             end; {with}
  945.     end;
  946.  
  947.  
  948.     procedure ChangeBrightness;
  949.         var
  950.             loc, oldloc, max, HalfMax, thumb, xcenter, ycenter, delta: integer;
  951.             hrect: rect;
  952.  
  953.         function FindLoc: integer;
  954.             var
  955.                 p: point;
  956.                 loc: integer;
  957.         begin
  958.             GetMouse(p);
  959.             loc := p.h - gmSlide1.left - 2;
  960.             if loc < 0 then
  961.                 loc := 0;
  962.             if loc > max + 5 then
  963.                 loc := max + 5;
  964.             FindLoc := loc;
  965.         end;
  966.  
  967.     begin
  968.         with info^ do begin
  969.                 thumb := gmSlideHeight - 2;
  970.                 max := gmSlideWidth - thumb - 2;
  971.                 HalfMax := max div 2;
  972.                 OldLoc := FindLoc;
  973.                 repeat
  974.                     xcenter := p1x + (p2x - p1x) div 2;
  975.                     ycenter := p1y + (p2y - p1y) div 2;
  976.                     loc := FindLoc;
  977.                     delta := gmSlide1Loc + 1 - loc;
  978.                     if deltay <> 0 then begin
  979.                             xcenter := xcenter + delta;
  980.                             if xcenter < 0 then
  981.                                 xcenter := 0;
  982.                             if xcenter > 255 then
  983.                                 xcenter := 255;
  984.                         end;
  985.                     if deltax <> 0 then begin
  986.                             ycenter := ycenter - delta;
  987.                             if ycenter < 0 then
  988.                                 ycenter := 0;
  989.                             if ycenter > 255 then
  990.                                 ycenter := 255;
  991.                         end;
  992.                     FindEndPoints(xcenter, ycenter);
  993.                     UpdateGrayMap;
  994.                     gmFixedSlope := true;
  995.                     SetGrayScaleLUT;
  996.                     gmFixedSlope := false;
  997.                     OldLoc := loc;
  998.                 until not button;
  999.                 IdentityFunction := false;
  1000.             end; {with}
  1001.     end;
  1002.  
  1003.  
  1004.     procedure ChangeContrast;
  1005.         var
  1006.             p: point;
  1007.             loc, max, HalfMax, thumb, xcenter, ycenter: integer;
  1008.             hrect: rect;
  1009.             slope: extended;
  1010.     begin
  1011.         with info^ do begin
  1012.                 thumb := gmSlideHeight - 2;
  1013.                 max := gmSlideWidth - thumb - 2;
  1014.                 HalfMax := max div 2;
  1015.                 xcenter := p1x + deltax div 2;
  1016.                 ycenter := p1y + deltay div 2;
  1017.                 repeat
  1018.                     GetMouse(p);
  1019.                     loc := p.h - gmSlide2.left - 2;
  1020.                     if loc < 0 then
  1021.                         loc := 0;
  1022.                     if loc > max then
  1023.                         loc := max;
  1024.                     if loc <= HalfMax then
  1025.                         slope := loc / HalfMax
  1026.                     else if loc < max then
  1027.                         slope := HalfMax / (max - loc)
  1028.                     else
  1029.                         slope := 1000.0;
  1030.                     if slope <= 1.0 then begin
  1031.                             deltax := 255;
  1032.                             deltay := round(slope * deltax);
  1033.                         end
  1034.                     else begin
  1035.                             deltay := 255;
  1036.                             deltax := round(deltay / slope);
  1037.                         end;
  1038.                     FindEndPoints(xcenter, ycenter);
  1039.                     UpdateGrayMap;
  1040.                     SetGrayScaleLUT;
  1041.                 until not button;
  1042.                 IdentityFunction := false;
  1043.             end; {with}
  1044.     end;
  1045.  
  1046.  
  1047.     procedure ConvertMouseToXY (p: point; var x, y: integer);
  1048.     begin
  1049.         x := (p.h - gmRectLeft) * 4;
  1050.         if x < 0 then
  1051.             x := 0;
  1052.         if x > 255 then
  1053.             x := 255;
  1054.         y := (gmRectBottom - p.v) * 4;
  1055.         if y < 0 then
  1056.             y := 0;
  1057.         if y > 255 then
  1058.             y := 255;
  1059.     end;
  1060.  
  1061.     procedure DoMouseDownInGrayMap;
  1062.         var
  1063.             r: rect;
  1064.             tPort: GrafPtr;
  1065.             x, y, p1Dist, p2Dist, x1, y1: integer;
  1066.             mode: (StartPoint, EndPoint, Brightness);
  1067.             p: point;
  1068.             pressed: boolean;
  1069.  
  1070.         procedure DoFixup;
  1071.         begin
  1072.             with info^ do
  1073.                 if ((p1x = 0) and (p2x = 0)) or ((p1x = 255) and (p2x = 255)) then begin
  1074.                         p1y := 0;
  1075.                         p2y := 255;
  1076.                     end;
  1077.         end;
  1078.  
  1079.     begin
  1080.         StopThresholding;
  1081.         ValuesMode := xyValues;
  1082.         DrawLabels;
  1083.         if info^.LUTMode = CustomGrayscale then
  1084.             ResetGrayMap;
  1085.         GetPort(tPort);
  1086.         SetPort(GrayMapWindow);
  1087.         GetMouse(p);
  1088.         if PtInRect(p, gmIcon1) then begin
  1089.                 InvertRect(gmIcon1);
  1090.                 pressed := true;
  1091.                 while Button and pressed do begin
  1092.                         GetMouse(p);
  1093.                         if not PtInRect(p, gmIcon1) then begin
  1094.                                 InvertRect(gmIcon1);
  1095.                                 pressed := false;
  1096.                             end;
  1097.                     end;
  1098.                 repeat
  1099.                 until not button;
  1100.                 if pressed then begin
  1101.                         InvertRect(gmIcon1);
  1102.                         ResetGrayMap;
  1103.                         SetPort(tPort);
  1104.                         exit(DoMouseDownInGrayMap)
  1105.                     end;
  1106.             end;
  1107.         if PtInRect(p, gmIcon2) then begin
  1108.                 InvertRect(gmIcon2);
  1109.                 pressed := true;
  1110.                 while Button and pressed do begin
  1111.                         GetMouse(p);
  1112.                         if not PtInRect(p, gmIcon2) then begin
  1113.                                 InvertRect(gmIcon2);
  1114.                                 pressed := false;
  1115.                             end;
  1116.                     end;
  1117.                 repeat
  1118.                 until not button;
  1119.                 if pressed then begin
  1120.                         InvertRect(gmIcon2);
  1121.                         with info^ do begin
  1122.                                 DeltaX := 1;
  1123.                                 DeltaY := 255;
  1124.                                 p1x := 128;
  1125.                                 p1y := 0;
  1126.                                 p2x := 128;
  1127.                                 p2y := 255;
  1128.                                 SetGrayScaleLUT;
  1129.                                 UpdateGrayMap;
  1130.                             end;
  1131.                         SetPort(tPort);
  1132.                         exit(DoMouseDownInGrayMap)
  1133.                     end;
  1134.             end;
  1135.         if PtInRect(p, gmSlide1) then
  1136.             ChangeBrightness;
  1137.         if PtInRect(p, gmSlide2) then
  1138.             ChangeContrast;
  1139.         if p.v > (gmRectBottom + 4) then begin
  1140.                 SetPort(tPort);
  1141.                 exit(DoMouseDownInGrayMap);
  1142.             end;
  1143.         GetMouse(p);
  1144.         ConvertMouseToXY(p, x, y);
  1145.         if (x <= 24) or (y <= 32) then
  1146.             mode := StartPoint
  1147.         else if (x >= 224) or (y >= 232) then
  1148.             mode := EndPoint
  1149.         else
  1150.             mode := brightness;
  1151.         repeat
  1152.             with info^ do
  1153.                 case mode of
  1154.                     StartPoint: 
  1155.                         begin
  1156.                             if x > y then
  1157.                                 y := 0
  1158.                             else
  1159.                                 x := 0;
  1160.                             p1x := x;
  1161.                             if p1x > p2x then
  1162.                                 p2x := p1x;
  1163.                             p1y := y;
  1164.                             if p1y > p2y then
  1165.                                 p2y := p1y;
  1166.                             DoFixUp;
  1167.                             Show2Values(p1x, p1y);
  1168.                         end;
  1169.                     EndPoint: 
  1170.                         begin
  1171.                             if x > y then
  1172.                                 x := 255
  1173.                             else
  1174.                                 y := 255;
  1175.                             p2x := x;
  1176.                             if p2x < p1x then
  1177.                                 p1x := p2x;
  1178.                             p2y := y;
  1179.                             if p2y < p1y then
  1180.                                 p1y := p2y;
  1181.                             DoFixUp;
  1182.                             Show2Values(p2x, p2y);
  1183.                         end;
  1184.                     Brightness: 
  1185.                         FindEndPoints(x, y);
  1186.                 end; {case}
  1187.             UpdateGrayMap;
  1188.             gmFixedSlope := mode = brightness;
  1189.             SetGrayScaleLUT;
  1190.             gmFixedSlope := false;
  1191.             GetMouse(p);
  1192.             ConvertMouseToXY(p, x, y);
  1193.         until not Button;
  1194.         SetPort(tPort);
  1195.         IdentityFunction := false;
  1196.     end;
  1197.  
  1198. end.